/*
 * Copyright (c) 2018, apexes.net. All rights reserved.
 *
 *         http://www.apexes.net
 *
 */
package net.apexes.wsonrpc.json.support.gson;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import net.apexes.wsonrpc.json.JsonRpcRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Type;

/**
 * @author <a href=mailto:hedyn@foxmail.com>HeDYn</a>
 */
public class GsonJsonRpcRequest implements JsonRpcRequest {

    private static final Logger LOG = LoggerFactory.getLogger(GsonJsonRpcRequest.class);

    private final Gson gson;
    private final JsonObject jsonObject;
    private final String id;
    private final String trace;
    private final String method;
    private final JsonArray params;

    protected GsonJsonRpcRequest(Gson gson, JsonObject jsonObject) {
        this.gson = gson;
        this.jsonObject = jsonObject;

        if (jsonObject.has("id")) {
            JsonElement element = jsonObject.get("id");
            if (element.isJsonNull()) {
                this.id = null;
            } else {
                this.id = element.getAsString();
            }
        } else {
            this.id = null;
        }
        JsonElement traceElement = jsonObject.get("trace");
        this.trace = traceElement == null ? null : traceElement.getAsString();
        this.method = jsonObject.get("method").getAsString();
        this.params = jsonObject.getAsJsonArray("params");
    }

    @Override
    public String getId() {
        return id;
    }

    @Override
    public String getTrace() {
        return trace;
    }

    @Override
    public String getMethod() {
        return method;
    }

    @Override
    public int getParamCount() {
        if (params == null) {
            return 0;
        }
        return params.size();
    }

    @Override
    public Object getParams() {
        return params;
    }

    @Override
    public Object[] getParams(Type[] types) {
        if (params == null) {
            return new Object[0];
        }
        try {
            Object[] args = new Object[types.length];
            for (int i = 0; i < args.length; i++) {
                JsonElement param = params.get(i);
                if (param.isJsonNull()) {
                    args[i] = null;
                } else {
                    args[i] = gson.fromJson(param, types[i]);
                }
            }
            return args;
        } catch (Exception e) {
            LOG.debug("params error!", e);
            return null;
        }
    }

    @Override
    public String getParamsAsJson() {
        return gson.toJson(params);
    }

    @Override
    public Object getParam(int index) {
        return params.get(index);
    }

    @Override
    public String getParamAsJson(int index) {
        return gson.toJson(getParam(index));
    }

    @Override
    public String toJson() {
        return gson.toJson(jsonObject);
    }

    @Override
    public boolean isRequest() {
        return true;
    }

    @Override
    public boolean isResponse() {
        return false;
    }
}
